use std::collections::HashSet;

use shq_common::prelude::{
    empl::EmployeeCache, get_expr_context_from_table,
};

use super::{
    cache::{ExecutorInfo, SaveType}, get_executor, FlowCache, TaskStatus
};
use crate::{config::{get_workflow_config, ExecutorType}, extend::ExecutorFunc};
pub(super) async fn get_user_from_conf(
    runid: u64,
    wfid: u32,
    version: u8,
    step_id: u8,
) -> anyhow::Result<Vec<ExecutorInfo>> {
    let conf = get_workflow_config(wfid, version).ok_or(anyhow::anyhow!(
        "WFID:{},version:{version}在配置中不存在",
        wfid
    ))?;
    let step = conf.get_step(step_id).ok_or(anyhow::anyhow!(
        "在配置WFID:{}中不存在step:{}",
        wfid,
        step_id
    ))?;
    let mut res: Vec<ExecutorInfo> = Vec::new();
    if let Some(ep)=step.expr_parser.as_ref() {
        let wc = format!("{}={}", conf.flow_run_id_col, runid);
        let cont =
            get_expr_context_from_table(&conf.table_name, ep.get_col_names(), &wc).await?;
        let is_ok = ep.eval(cont)?.as_boolean()?;
        if !is_ok {
            return Ok(res);
        }
    }
    for e in step.executors.iter() {
        if let Some(ep) = e.expr_parser.as_ref() {
            let wc = format!("{}={}", conf.flow_run_id_col, runid);
            let cont =
                get_expr_context_from_table(&conf.table_name, ep.get_col_names(), &wc).await?;
            let is_ok = ep.eval(cont)?.as_boolean()?;
            if !is_ok {
                continue;
            }
        }
        match e.r#type {
            crate::config::ExecutorType::Role => {
                let ids = get_user_by_role_ids(runid, e.ids.as_ref(), e.organ_from_step).await?;
                let sids: Vec<ExecutorInfo> = ids
                    .into_iter()
                    .map(|id| ExecutorInfo {
                        user_id: id,
                        task_state: TaskStatus::None,
                        start_time: None,
                        submit_time: None,
                        feed_back: None,
                        save_type: SaveType::None,
                    })
                    .collect();
                res.extend(sids);
            }
            crate::config::ExecutorType::User => {
                let sids: Vec<ExecutorInfo> = e
                    .ids
                    .iter()
                    .map(|id| ExecutorInfo {
                        user_id: *id,
                        task_state: TaskStatus::None,
                        start_time: None,
                        submit_time: None,
                        feed_back: None,
                        save_type: SaveType::None,
                    })
                    .collect();
                res.extend(sids);
            }
            crate::config::ExecutorType::Func => {
                let func_name = e.func_name.as_ref().ok_or(anyhow::anyhow!(
                    "在配置WFID:{wfid},step:{step_id}中func_name不能为空"
                ))?;
                let ids = get_user_by_func(runid, step_id, func_name).await?;
                let sids: Vec<ExecutorInfo> = ids
                    .into_iter()
                    .map(|id| ExecutorInfo {
                        user_id: id,
                        task_state: TaskStatus::None,
                        start_time: None,
                        submit_time: None,
                        feed_back: None,
                        save_type: SaveType::None,
                    })
                    .collect();
                res.extend(sids);
            }
        }
    }
    Ok(res)
}
pub(crate) async fn get_managers(wfid: u32,version: u8) -> anyhow::Result<Vec<u32>> {
    let conf = get_workflow_config(wfid, version).ok_or(anyhow::anyhow!(
        "WFID:{},version:{version}在配置中不存在",
        wfid
    ))?;
    let mut res: Vec<u32> = Vec::new();
    for me in conf.managers.iter() {
        if me.r#type==ExecutorType::User {
            res.extend(me.ids.iter());
        }else if  me.r#type==ExecutorType::Role {
            for rid in me.ids.iter() {
                let ids = shq_auth::get_role_user_ids(*rid).await?;
                res.extend(ids);
            }
        }
    }
    Ok(res)
}
pub(super) async fn get_user_by_role_ids(
    run_id: u64,
    role_ids: &Vec<u32>,
    organ_from_step: Option<u8>,
) -> anyhow::Result<Vec<u32>> {
    let mut res: Vec<u32> = Vec::new();
    let mut ec = EmployeeCache::new()?;
    let mut limit_dpids: HashSet<u32> = HashSet::new();
    if let Some(organ_from_step) = organ_from_step {
        let users=Box::pin(get_executor(run_id, organ_from_step,None)).await?;
        let mut fuc = FlowCache::from(run_id)?;
        let fi = fuc.get_flow_info().await?;
        for u in users.into_iter() {
            if organ_from_step<fi.step_id && u.task_state != TaskStatus::Done {
                continue;
            }
            if organ_from_step==fi.step_id && u.task_state != TaskStatus::Doing {
                continue;
            }
            let e = ec.get_empl_by_id(u.user_id).await?;
            limit_dpids.insert(e.organ_id);
        }
    }
    for role_id in role_ids.into_iter() {
        let user_ids = shq_auth::get_role_user_ids(*role_id).await?;
        if organ_from_step.is_some() {
            if !limit_dpids.is_empty() {
                for uid in user_ids.into_iter() {
                    let e = ec.get_empl_by_id(uid).await?;
                    if limit_dpids.contains(&e.organ_id) {
                        res.push(uid);
                    }
                }
            }
        }else{
            res.extend(user_ids);
        }
    }
    Ok(res)
}

pub(super) async fn get_user_by_func(
    run_id: u64,
    step_id: u8,
    func_name: &str,
) -> anyhow::Result<Vec<u32>> {
    let ef = ExecutorFunc::new(func_name);
    ef.exec(run_id, step_id).await
}
